unit GLGUIBoundedLabel;

interface

uses
  Classes,
  GLGUIFonts,
  GLGUITextComponent,
  GLGUITokens,
  GLGUILabel;

type
  TGLGUIBoundedLabel = class(TGLGUILabel)
  protected
    FPointsWidth: Single;
    FAutoBound: Boolean;
    FMaxWidth: Single;
    procedure SetText(const AText: String); override;
    function GetWidth: Single; override;
    procedure SetWidth(const AWidth: Single); override;
    procedure SetFont(const AFont: TGLGUIBitmapFont); override;
    function GetAutoBound: Boolean;
    procedure SetAutoBound(AAutoBound: Boolean);
    function GetPointsWidth(): Single;
  public
    constructor Create(AOwner: TComponent); override;
    property AutoBound: Boolean read GetAutoBound write SetAutoBound default True;
    property MaxWidth: Single read FMaxWidth;
    property PointsWidth: Single read GetPointsWidth;
  end;

implementation

constructor TGLGUIBoundedLabel.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FAutoBound := True;
  Enabled := False;
end;

procedure TGLGUIBoundedLabel.SetText(const AText: String);
var
  i, j: Integer;
  vChar: TGLGUICharQuad;
begin
  if FAutoBound then
  begin
    FText := AText;
    FMaxWidth := TextWidth;
    FCarretX := 0;

    for i := 0 to FGlyphs.Count - 1 do
      FGlyphs.Items[i].Free;

    FGlyphs.Clear;

    if (FWidth<FPointsWidth) then
      Exit;

    for i := 1 to length(FText) do
    begin
      vChar := AddChar(AText[i]);
      FCarretX := FCarretX + vChar.Info.Width / 2 + FLetterSpacing;
      if (FCarretX < FWidth - FPointsWidth) then
      begin
        vChar.X := FCarretX;
        FCarretX := FCarretX + vChar.Info.CharWidth - vChar.Info.Width / 2;
        FGlyphs.Add(vChar);
      end
      else
      begin
        FCarretX := FCarretX - vChar.Info.Width / 2 + FLetterSpacing;
        vChar.Free;
        for j := 0 to 2 do
        begin
          vChar := AddChar('.');
          FCarretX := FCarretX + vChar.Info.Width / 2 + FLetterSpacing;
          vChar.X := FCarretX;
          FCarretX := FCarretX + vChar.Info.CharWidth - vChar.Info.Width / 2;
          FGlyphs.Add(vChar);
        end;
        Break;
      end;
    end;

    for i := 0 to FGlyphs.Count - 1 do
      FGlyphs[i].X := FGlyphs[i].X - FMaxWidth/2;
    FNeedUpdate := True;
  end
  else
    inherited;
end;

function TGLGUIBoundedLabel.GetWidth: Single;
begin
  Result := FWidth;
end;

procedure TGLGUIBoundedLabel.SetWidth(const AWidth: Single);
begin
  if AWidth <> FWidth then
    FWidth := AWidth;
  if FAutoBound then
    Text := FText;
end;

procedure TGLGUIBoundedLabel.SetFont(const AFont: TGLGUIBitmapFont);
begin
  FUpdateTextOnFontChange := False;
  inherited;
  FPointsWidth := FFont.GetGlyphInfo('.').Width * 3;
  Text := FText;
  FUpdateTextOnFontChange := True;
end;

function TGLGUIBoundedLabel.GetAutoBound: Boolean;
begin
  Result := FAutoBound;
end;

procedure TGLGUIBoundedLabel.SetAutoBound(AAutoBound: Boolean);
begin
  FAutoBound := AAutoBound;
end;

function TGLGUIBoundedLabel.GetPointsWidth(): Single;
begin
  Result := FPointsWidth;
end;

end.
